import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:intl/intl.dart' hide TextDirection;

// 无限滑动时间刻度组件
class InfiniteTimeScale extends LeafRenderObjectWidget {
  // 组件高度
  final double height;
  // 可视宽度
  final double visibleWidth;
  // 初始时间
  final DateTime initialTime;
  // 时间变化回调
  final ValueChanged<DateTime>? onTimeChanged;
  // 最小时间间隔（分钟）
  final int minuteInterval;
  // 是否显示上午/下午
  final bool showAmPm;

  InfiniteTimeScale({
    super.key,
    this.height = 120.0,
    this.visibleWidth = 300.0,
    DateTime? initialTime,
    this.onTimeChanged,
    this.minuteInterval = 15,
    this.showAmPm = true,
  })  : initialTime = initialTime ?? DateTime.now(),
        assert(minuteInterval > 0 && 60 % minuteInterval == 0);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderInfiniteTimeScale(
      height: height,
      visibleWidth: visibleWidth,
      initialTime: initialTime,
      onTimeChanged: onTimeChanged,
      minuteInterval: minuteInterval,
      showAmPm: showAmPm,
    );
  }

  @override
  void updateRenderObject(BuildContext context, RenderInfiniteTimeScale renderObject) {
    renderObject
      ..height = height
      ..visibleWidth = visibleWidth
      ..minuteInterval = minuteInterval
      ..showAmPm = showAmPm
      ..onTimeChanged = onTimeChanged;
  }
}

// 时间刻度渲染对象
class RenderInfiniteTimeScale extends RenderBox {
  double _height;
  double _visibleWidth;
  DateTime _currentTime;
  ValueChanged<DateTime>? _onTimeChanged;
  int _minuteInterval;
  bool _showAmPm;
  
  // 滑动偏移量
  double _offsetX = 0.0;
  // 每个时间间隔的像素宽度
  double get _intervalPixelWidth => 40.0;
  // 一个周期的宽度（24小时）
  double get _cycleWidth => (24 * 60 / _minuteInterval) * _intervalPixelWidth;
  
  // 触摸状态
  double? _startTouchX;
  double? _startOffsetX;
  bool _isDragging = false;

  RenderInfiniteTimeScale({
    required double height,
    required double visibleWidth,
    required DateTime initialTime,
    ValueChanged<DateTime>? onTimeChanged,
    required int minuteInterval,
    required bool showAmPm,
  })  : _height = height,
        _visibleWidth = visibleWidth,
        _currentTime = _roundToInterval(initialTime, minuteInterval),
        _onTimeChanged = onTimeChanged,
        _minuteInterval = minuteInterval,
        _showAmPm = showAmPm {
    // 根据初始时间计算偏移量
    _offsetX = _getTimeOffset(_currentTime);
  }

  // 将时间四舍五入到最近的时间间隔
  static DateTime _roundToInterval(DateTime time, int interval) {
    final minutes = time.hour * 60 + time.minute;
    final roundedMinutes = (minutes / interval).round() * interval;
    return DateTime(
      time.year,
      time.month,
      time.day,
      roundedMinutes ~/ 60,
      roundedMinutes % 60,
    );
  }

  // 计算时间对应的偏移量
  double _getTimeOffset(DateTime time) {
    final totalMinutes = time.hour * 60 + time.minute;
    return (totalMinutes / _minuteInterval) * _intervalPixelWidth;
  }

  // 根据偏移量计算对应的时间
  DateTime _getOffsetTime(double offset) {
    final normalizedOffset = (offset % _cycleWidth + _cycleWidth) % _cycleWidth;
    final intervals = (normalizedOffset / _intervalPixelWidth).round();
    final totalMinutes = intervals * _minuteInterval;
    
    // 计算小时和分钟
    final hours = totalMinutes ~/ 60;
    final minutes = totalMinutes % 60;
    
    // 创建基于当前日期的时间对象
    return DateTime(
      _currentTime.year,
      _currentTime.month,
      _currentTime.day,
      hours,
      minutes,
    );
  }

  // 设置属性的setter
  set height(double value) {
    if (_height != value) {
      _height = value;
      markNeedsLayout();
    }
  }

  set visibleWidth(double value) {
    if (_visibleWidth != value) {
      _visibleWidth = value;
      markNeedsLayout();
    }
  }

  set minuteInterval(int value) {
    if (_minuteInterval != value && value > 0 && 60 % value == 0) {
      _minuteInterval = value;
      // 重新计算偏移量以匹配新的时间间隔
      _offsetX = _getTimeOffset(_currentTime);
      markNeedsPaint();
    }
  }

  set showAmPm(bool value) {
    if (_showAmPm != value) {
      _showAmPm = value;
      markNeedsPaint();
    }
  }

  set onTimeChanged(ValueChanged<DateTime>? value) {
    _onTimeChanged = value;
  }

  // 标准化偏移量，实现24小时无限循环
  void _normalizeOffset() {
    _offsetX = _offsetX % _cycleWidth;
    if (_offsetX < 0) _offsetX += _cycleWidth;
  }

  // 吸附到最近的时间间隔
  void _snapToInterval() {
    final intervals = (_offsetX / _intervalPixelWidth).round();
    _offsetX = intervals * _intervalPixelWidth;
    _normalizeOffset();
    
    // 更新当前时间并通知
    final newTime = _getOffsetTime(_offsetX);
    if (!_currentTime.isAtSameMomentAs(newTime)) {
      _currentTime = newTime;
      _onTimeChanged?.call(_currentTime);
    }
    
    markNeedsPaint();
  }

  // 处理触摸事件
  @override
  bool hitTestSelf(Offset position) => true;

  @override
  void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
    super.handleEvent(event, entry);

    if (event is PointerDownEvent) {
      _startTouchX = event.localPosition.dx;
      _startOffsetX = _offsetX;
      _isDragging = true;
    } else if (event is PointerMoveEvent && _startTouchX != null && _startOffsetX != null) {
      // 计算滑动偏移
      final deltaX = event.localPosition.dx - _startTouchX!;
      _offsetX = _startOffsetX! - deltaX; // 反向滑动
      
      _normalizeOffset();
      markNeedsPaint();
    } else if ((event is PointerUpEvent || event is PointerCancelEvent) && _isDragging) {
      _isDragging = false;
      _startTouchX = null;
      _startOffsetX = null;
      
      // 滑动结束后吸附到最近的时间点
      _snapToInterval();
    }
  }

  // 布局逻辑
  @override
  void performLayout() {
    size = Size(_visibleWidth, _height);
  }

  // 绘制时间刻度
  void _paintTimeScale(Canvas canvas, Offset offset) {
    final mainPaint = Paint()
      ..color = Colors.black87
      ..strokeWidth = 1.5;
      
    final subPaint = Paint()
      ..color = Colors.black54
      ..strokeWidth = 1.0;

    // 主刻度高度和次刻度高度
    const mainScaleHeight = 30.0;
    const subScaleHeight = 15.0;
    final centerY = offset.dy + _height / 2;

    // 计算需要绘制的周期范围
    final visibleIntervals = (_visibleWidth / _intervalPixelWidth).ceil() + 2;
    final centerInterval = (_offsetX / _intervalPixelWidth).round();
    
    // 绘制可见范围内的刻度
    for (int i = -visibleIntervals; i <= visibleIntervals; i++) {
      final interval = centerInterval + i;
      final x = offset.dx + _visibleWidth / 2 + i * _intervalPixelWidth;
      
      // 计算这个刻度对应的时间
      final totalMinutes = interval * _minuteInterval;
      final hours = totalMinutes ~/ 60 % 24;
      final minutes = totalMinutes % 60;
      
      // 判断是否为主刻度（整点）
      final isMainScale = minutes == 0;
      
      // 绘制刻度线
      canvas.drawLine(
        Offset(x, centerY - (isMainScale ? mainScaleHeight : subScaleHeight)),
        Offset(x, centerY + (isMainScale ? mainScaleHeight : subScaleHeight)),
        isMainScale ? mainPaint : subPaint,
      );
      
      // 绘制时间文本（仅主刻度）
      if (isMainScale) {
        String timeText;
        if (_showAmPm) {
          // 12小时制带上午/下午
          timeText = DateFormat('h a').format(
            DateTime(2023, 1, 1, hours)
          );
        } else {
          // 24小时制
          timeText = DateFormat('HH:00').format(
            DateTime(2023, 1, 1, hours)
          );
        }
        
        final textPainter = TextPainter(
          text: TextSpan(
            text: timeText,
            style: TextStyle(
              color: Colors.black87,
              fontSize: isMainScale ? 12 : 10,
              fontWeight: isMainScale ? FontWeight.bold : FontWeight.normal,
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        textPainter.layout();
        textPainter.paint(
          canvas,
          Offset(
            x - textPainter.width / 2,
            centerY + mainScaleHeight + 5,
          ),
        );
      }
    }
  }

  // 绘制当前时间指示器
  void _paintIndicator(Canvas canvas, Offset offset) {
    final centerX = offset.dx + _visibleWidth / 2;
    final centerY = offset.dy + _height / 2;
    
    // 绘制中心竖线
    canvas.drawLine(
      Offset(centerX, offset.dy + 20),
      Offset(centerX, offset.dy + _height - 20),
      Paint()
        ..color = Colors.blue
        ..strokeWidth = 2.0
        ..strokeCap = StrokeCap.round,
    );
    
    // 绘制上下箭头
    const arrowSize = 8.0;
    
    // 上箭头
    final topArrow = Path();
    topArrow.moveTo(centerX - arrowSize, offset.dy + 20);
    topArrow.lineTo(centerX + arrowSize, offset.dy + 20);
    topArrow.lineTo(centerX, offset.dy + 20 - arrowSize);
    topArrow.close();
    
    // 下箭头
    final bottomArrow = Path();
    bottomArrow.moveTo(centerX - arrowSize, offset.dy + _height - 20);
    bottomArrow.lineTo(centerX + arrowSize, offset.dy + _height - 20);
    bottomArrow.lineTo(centerX, offset.dy + _height - 20 + arrowSize);
    bottomArrow.close();
    
    canvas.drawPath(topArrow, Paint()..color = Colors.blue);
    canvas.drawPath(bottomArrow, Paint()..color = Colors.blue);
  }

  // 绘制当前时间显示
  void _paintTimeDisplay(Canvas canvas, Offset offset) {
    final timeFormat = _showAmPm ? DateFormat('h:mm a') : DateFormat('HH:mm');
    final timeText = timeFormat.format(_currentTime);
    
    final textPainter = TextPainter(
      text: TextSpan(
        text: timeText,
        style: const TextStyle(
          color: Colors.black87,
          fontSize: 18,
          fontWeight: FontWeight.bold,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    textPainter.paint(
      canvas,
      Offset(
        offset.dx + (_visibleWidth - textPainter.width) / 2,
        offset.dy + 10,
      ),
    );
  }

  // 绘制背景和网格
  void _paintBackground(Canvas canvas, Offset offset) {
    // 绘制背景
    canvas.drawRect(
      offset & size,
      Paint()..color = Colors.grey[50]!,
    );
    
    // 绘制中心水平线
    final centerY = offset.dy + _height / 2;
    canvas.drawLine(
      Offset(offset.dx, centerY),
      Offset(offset.dx + _visibleWidth, centerY),
      Paint()
        ..color = Colors.grey[300]!
        ..strokeWidth = 1.0
        ..strokeCap = StrokeCap.round
        ..style = PaintingStyle.stroke
    );
  }

  // 总绘制逻辑
  @override
  void paint(PaintingContext context, Offset offset) {
    final canvas = context.canvas;
    
    canvas.save();
    
    // 1. 绘制背景
    _paintBackground(canvas, offset);
    
    // 2. 绘制时间刻度
    _paintTimeScale(canvas, offset);
    
    // 3. 绘制指示器
    _paintIndicator(canvas, offset);
    
    // 4. 绘制当前时间
    _paintTimeDisplay(canvas, offset);
    
    canvas.restore();
  }

  @override
  bool get isRepaintBoundary => true;
}

// 使用示例
class TimeScaleDemo extends StatelessWidget {
  const TimeScaleDemo({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('无限滑动时间刻度')),
      body: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            const Text('左右滑动选择时间：'),
            const SizedBox(height: 20),
            InfiniteTimeScale(
              visibleWidth: 350,
              height: 150,
              minuteInterval: 15, // 15分钟一个间隔
              showAmPm: true,
            ),
            const SizedBox(height: 20),
            const Text('蓝色指针指向的位置即为选中的时间'),
          ],
        ),
      ),
    );
  }
}

